package org.ranch.api.security.service.impl;

import java.util.ArrayList;
import java.util.List;

import org.ranch.api.security.RanchUserDetails;
import org.ranch.api.security.service.RanchUserDetailsService;
import org.ranch.dao.PermissionDAO;
import org.ranch.dao.UserDAO;
import org.ranch.model.Permission;
import org.ranch.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.transaction.annotation.Transactional;

/**
 * This class is responsible for loading a {@link MohrUserDetails} object for a
 * given {@link User}
 * 
 */
public class RanchUserDetailsServiceImpl implements RanchUserDetailsService {

    @Autowired
    private UserDAO userDAO;
    @Autowired
    private PermissionDAO permissionDAO;

    /*
     * (non-Javadoc)
     * 
     * @see org.mak.cis.mohr.api.security.service.MohrUserDetailsService#
     * getUserDetailsForUser(org.mak.cis.mohr.model.User)
     */
    @Override
    public RanchUserDetails getUserDetailsForUser(User user) {
        RanchUserDetails userDetails = null;
        if (user != null) {
            List<GrantedAuthority> authorities = getUserAuthorities(user);
            if (authorities == null) {
                authorities = new ArrayList<GrantedAuthority>();
            }

            userDetails = new RanchUserDetails(user, true, true, true, true, authorities);
        }

        return userDetails;
    }

    /**
     * gets a list of granted authorities for a given user
     * 
     * @param user
     * @return
     */
    protected List<GrantedAuthority> getUserAuthorities(User user) {
        List<GrantedAuthority> authorities = null;
        if (user != null) {
            authorities = new ArrayList<GrantedAuthority>();
            List<Permission> permissions = null;

            if (user.hasAdministrativePrivileges()) {
                permissions = permissionDAO.findAll();
            } else {
                permissions = user.findPermissions();
            }

            if (permissions != null && permissions.size() > 0) {
                for (Permission perm : permissions) {
                    GrantedAuthority ga = new GrantedAuthorityImpl(perm.getName());
                    authorities.add(ga);
                }
            }
        }

        return authorities;
    }

    /*
     * (non-Javadoc)
     * 
     * @seeorg.springframework.security.core.userdetails.UserDetailsService#
     * loadUserByUsername(java.lang.String)
     */
    @Override
    @Transactional
    public UserDetails loadUserByUsername(String username)
            throws UsernameNotFoundException, DataAccessException {
        try {
            User user = userDAO.searchUniqueByPropertyEqual("username", username);
            if (user != null) {
                return getUserDetailsForUser(user);
            }
        } catch (Exception e) {

            throw new UsernameNotFoundException(e.getMessage(), e);
        }

        return null;
    }
}
